package cxm.mmp.aud;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import cxm.lib.util.MyLog;


public class XAudioRecorder extends XAudioBase {
	private AudioRecord record = null;
	// private AcousticEchoCanceler echoCanceler = null;
	// private NoiseSuppressor ns = null;

	public XAudioRecorder() {
		// set channel type
		this.channel = AudioFormat.CHANNEL_IN_MONO;
	}
	
	protected int onBeforeRun() {
		// new audio record
		int min = AudioRecord.getMinBufferSize(this.freq,
				this.channel, this.audioFormat);
		this.record = new AudioRecord(MediaRecorder.AudioSource.MIC,
				this.freq, this.channel, this.audioFormat, min);
		
		/*
		// init AEC
		if (AcousticEchoCanceler.isAvailable()) {
			this.echoCanceler = AcousticEchoCanceler.create(this.record.getAudioSessionId());
			this.echoCanceler.setEnabled(true);
			if (this.echoCanceler.getEnabled())
				MyLog.Log(MyLog.Level.Warning, "Enable AEC");
			else
				MyLog.Log(MyLog.Level.Warning, "Enable AEC failed");
		}
		else
			MyLog.Log(MyLog.Level.Warning, "Do not support AEC");
		
		// init NS
		if (NoiseSuppressor.isAvailable()) {
			this.ns = NoiseSuppressor.create(this.record.getAudioSessionId());
			this.ns.setEnabled(true);
			if (this.ns.getEnabled())
				MyLog.Log(MyLog.Level.Info, "Ns enabled");
			else
				MyLog.Log(MyLog.Level.Error, "Cannot enable ns");
		}
		else
			MyLog.Log(MyLog.Level.Warning, "NS not support");
		*/

		// set thread priority
		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
		// start recording
		this.record.startRecording();

		return 0;
	}
	
	protected int onAfterRun() {
		this.record.stop();
		this.record.release();
		this.record = null;
		
		/*
		if (null != this.echoCanceler) {
			this.echoCanceler.setEnabled(false);
			this.echoCanceler.release();
		}
		if (null != this.ns) {
			this.ns.setEnabled(false);
			this.ns.release();
		}
		*/

		return 0;
	}
	
	protected int onRunOnce() {
		// read data from record
		int num = this.record.read(this.buffer, 0, this.buffer.length);
		if (num <= 0) {
			MyLog.Log(MyLog.Level.Error, "Cannot read recorded data: " + num);
			return num;
		}
		
		if (null == this.recording)
			return 0;
		
		// write data to IRecording
		int res = 0;
		while (res < num) {
			int ret = this.recording.onRecordData(buffer, res, num - res);
			if (ret <= 0) {
				// error handle
				MyLog.Log(MyLog.Level.Error, "Cannot process data with number" +
						num + " at " + res);
				return ret;
			}
			res += ret;
		}

		return 0;
	}
}
